package com.ftg.mall.base.util.bussiness;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ftg.mall.base.dto.DimDto;
import com.ftg.mall.base.entity.base.BaseEntity;
import com.ftg.mall.base.util.tooltips.ResBean;
import com.ftg.mall.base.util.SpringApplicationContext;
import com.ftg.mall.base.util.tooltips.TipEnum;
import com.mysql.cj.util.StringUtils;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.*;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Objects;

/**
 * 去掉构造方法引入
 *
 * @author kangjx
 * @createTime 2022/10/27
 */
@SuppressWarnings("all")
@Component
public abstract class AbstractController<T extends ServiceImpl, E extends BaseEntity> {

    private static final Logger log = LoggerFactory.getLogger(AbstractController.class);

    public IService<E> iService;

    /**
     * 基于mybatis plus完成service查找藣有
     */
    public void setIservice(){
        ParameterizedType ptClass = (ParameterizedType) this.getClass().getGenericSuperclass();
        Type[] ts = ptClass.getActualTypeArguments();

        if(Objects.isNull(ts) || ts[0] == null){
            log.warn("通用类" + this.getClass().getName(), TipEnum.FAIL_NOT_CONTROLLER_PARAMETERTYPE_TIP);
            throw new RuntimeException(TipEnum.FAIL_NOT_CONTROLLER_PARAMETERTYPE_TIP);
        }
        String servicePath = ts[0].getTypeName();
        try {
            Class serviceClass = Class.forName(servicePath);

            this.iService = (IService<E>) SpringApplicationContext.getBean(serviceClass);
        } catch (ClassNotFoundException e) {
            log.warn("通用类" + this.getClass().getName(),TipEnum.FAIL_PARAMETERTYPE_REFLECH_TIP);
            throw new RuntimeException(TipEnum.FAIL_PARAMETERTYPE_REFLECH_TIP);
        }
    }

    /**
     * 用来在自定义controller里面获得当前类的service实例
     * @return
     */
    public IService<E> getIService(){
        this.setIservice();
        return this.iService;
    }

    /**
     * 来自通用的添加实例方法
     * @param e 实体
     * @return ResBean
     */
    @PostMapping("/createEntity")
    @ApiOperation("来自通用的添加实例方法")
    public ResBean saveT(@RequestBody @ApiParam(value = "添加的实体") E e) {
        log.info("通用添加方法开始","实体为" + e.getClass().getName());
        if(this.getIService().save(e)){
            return ResBean.success(e);
        }
        log.warn("通用添加方法失败" + e);
        return ResBean.failure();
    }

    /**
     * 通用的添加方法
     * @param e 实体
     * @return ResBean
     */
    @PutMapping("/updateEntity")
    @ApiOperation("通用实体修改方法,按照主键")
    public ResBean modifyT(@RequestBody @ApiParam(value = "修改实体") E e) {
        log.info("通用修改方法开始","实体为" + e.getClass().getName());
        E e1 = this.getIService().getById(e.getId());
        if(Objects.isNull(e1)){
            log.warn(TipEnum.NO_DATA_TIP);
            return ResBean.noData();
        }
        if(!this.getIService().updateById(e)){
            log.warn(TipEnum.FAIL_DML_TIP);
            return ResBean.FAIL_DML();
        }
        log.info("修改操作已成功!!!");
        return ResBean.success();
    }


    /**
     * 通用的删除方法
     *
     * @param id 实体
     * @return ResBean
     */
    @DeleteMapping("/deleteT")
    @ApiOperation("通用的删除方法,按照主键")
    public ResBean deleteT(@RequestParam("id") @ApiParam(value = "主键", required = true) Serializable id) {
        log.info("通用删除方法开始","主键为:" + id);
        E e1 = this.getIService().getById(id);
        if(Objects.isNull(e1)){
            log.warn(TipEnum.NO_DATA_TIP);
            return ResBean.noData();
        }
        if(!this.getIService().removeById(id)){
            log.warn(TipEnum.FAIL_DML_TIP);
            return ResBean.FAIL_DML();
        }
        return ResBean.success();
    }

    /**
     * 通用的查询方法
     * @param id 主键
     * @return ResBean
     */
    @ApiOperation("通用主键查一操作")
    @PutMapping("/findone/{id}")
    public ResBean findOne(@PathVariable("id") @ApiParam(value = "主键") Serializable id) {
        log.info("通用主键查一操作","主键为:" + id);
        return ResBean.success(this.getIService().getById(id));
    }


    /**
     * 通用查看全部信息
     * @return ResBean
     */
    @GetMapping("/list")
    @ApiOperation("通用查看全部信息")
    public ResBean list() {
        List<E> list = this.getIService().list();
        if(Objects.isNull(list)){
            return ResBean.noData();
        }
        return ResBean.success(this.getIService().list());
    }

    /**
     * 通用的带参查看全部
     *
     * @param cols 大量列名
     * @param para 大量列名的参数
     * @return ResBean
     */
    @PostMapping("/listWithParam")
    @ApiOperation("通用的带参查看全部")
    @SuppressWarnings("all")
    public ResBean listWithParam(@RequestBody(required = false) @ApiParam(value = "模糊查询参数封装") DimDto dimDto) {
        QueryWrapper<E> queryWrapper = new QueryWrapper<>();
        if (Objects.nonNull(dimDto)) {
            for (int i = 0; i < dimDto.getCols().size(); i++) {
                if (!StringUtils.isNullOrEmpty(dimDto.getPara().get(i))) {
                    queryWrapper.like(dimDto.getCols().get(i), dimDto.getPara().get(i));
                }
            }
        }

        return ResBean.success(this.getIService().list(queryWrapper));
    }

    /**
     * 通用带模糊分页功能
     *
     * @param cols 大量列名
     * @param para 大量列名的参数
     * @return ResBean
     */
    @PostMapping("/pageWithParam")
    @ApiOperation("通用带模糊分页功能")
    @SuppressWarnings("all")
    public ResBean pageWithParam(
            @RequestParam("page") @ApiParam(value = "页码", defaultValue = "1") int page,
            @RequestParam("limit") @ApiParam(value = "显示条目", defaultValue = "10") int limit,
            @RequestBody(required = false) @ApiParam(value = "模糊查询参数封装") DimDto dimDto) {
        IPage<E> iPage = new Page<>(page, limit);

        QueryWrapper<E> queryWrapper = new QueryWrapper<>();
        if (Objects.nonNull(dimDto)) {
            for (int i = 0; i < dimDto.getCols().size(); i++) {
                if (!StringUtils.isNullOrEmpty(dimDto.getPara().get(i))) {
                    queryWrapper.like(dimDto.getCols().get(i), dimDto.getPara().get(i));
                }
            }
        }
        return ResBean.success(this.getIService().page(iPage, queryWrapper));
    }

}

